package com.mazaiting.instructions.references;

import com.mazaiting.instructions.base.ClassInitLogic;
import com.mazaiting.instructions.base.Index16Instruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.heap.MtClass;
import com.mazaiting.rtda.heap.MtConstant;
import com.mazaiting.rtda.heap.MtConstantPool;
import com.mazaiting.rtda.heap.MtObject;

/**
 * new 指令
 *
 * @author mazaiting
 * @since 2021/8/17
 */
public class NewInstruction {

    /**
     * new指令的操作数是一个uint16索引，来自字节码。通过这个索引，
     * 可以从当前类的运行时常量池中找到一个类符号引用。解析这个类符号引用，
     * 拿到类数据，然后创建对象，并把对象引用推入栈顶，new指令的工作就完成了。
     */
    public static class New extends Index16Instruction {
        @Override
        public void execute(MtFrame frame) {
            // 获取常量池
            MtConstantPool pool = frame.getMethod().getMtClass().getConstantPool();
            // 类引用
            MtConstant.MtClassRef classRef = (MtConstant.MtClassRef) pool.getConstant(index);
            // 解析类
            MtClass mtClass = classRef.resolvedClass();
            // 判断类是否已经初始化
            if (!mtClass.isInitStarted()) {
                frame.revertNextPc();
                ClassInitLogic.initClass(frame.getThread(), mtClass);
                return;
            }
            // 判断是否为接口或者抽象类
            if (mtClass.isInterface() || mtClass.isAbstract()) {
                throw new RuntimeException("java.lang.InstantiationError");
            }
            // 创建对象
            MtObject ref = mtClass.newObject();
            // 压入栈
            frame.getOperandStack().pushRef(ref);
        }

        @Override
        public String toString() {
            return "new " + index;
        }
    }

}


















